﻿using CommonModel.DB;
using CommonModel.Field;
using CommonModel.Model;
using CommonModel.Util;
using GXRTBTC.PublicClassLibrary.Field;
using GXRTBTC.PublicClassLibrary.Util;
using Microsoft.EntityFrameworkCore;
using NewLife.Log;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.IO;
using System.Xml.Linq;

namespace PtlSvr.CfgLoader
{
    public class SchemaServer
    {
        /// <summary>
        /// 读取xml配置
        /// 从文件读取
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static Dictionary<string, SchemaDocument> InitSchemaMapFromXMLFile(string path)
        {
            Dictionary<string, SchemaDocument> schemaDict = new Dictionary<string, SchemaDocument>();
            string[] schemaFiles = Directory.GetFiles(path, "*.xml");
            if (null == schemaFiles || schemaFiles.Length == 0)
            {
                XTrace.Log.Info("文件夹[" + path + "]下没有xml文件！");
                return schemaDict;
            }

            SchemaParseByCfg schemaParser = new();
            foreach (string file in schemaFiles)
            {
                SchemaDocument schDoc = schemaParser.parse(file);
                if (null != schDoc)
                {
                    //如果xmlType不为空，做处理
                    string schemaxmlType = schDoc.xmlType;
                    if (schemaxmlType != null && schemaxmlType != "")
                    {
                        string[] xmlTypeArray = schemaxmlType.Split(",");
                        for (int i = 0; i < xmlTypeArray.Length; i++)
                        {
                            schemaDict.Add(xmlTypeArray[i].Trim(), schDoc);
                        }
                    }
                    else
                    {
                        schemaDict.Add(schDoc.name, schDoc);
                    }
                }
            }
            return schemaDict;
        }

        /// <summary>
        /// 读取xml配置
        /// 从数据库读取
        /// </summary>
        /// <param name="dbConnection"></param>
        /// <returns></returns>
        public static Dictionary<string, SchemaDocument> InitSchemaMapFromDb(DbConnection dbConnection)
        {
            Dictionary<string, SchemaDocument> tmpDict = new Dictionary<string, SchemaDocument>();
            Dictionary<string, SchemaDocument> schemaDict = new Dictionary<string, SchemaDocument>();

            //从主表获取
            DbCommand dbCommand = dbConnection.CreateCommand();
            dbCommand.CommandText = "SELECT id, file_name, schema_name, msg_type, COALESCE(xml_type, '') xml_type, COALESCE(prefix_cols, '') prefix_cols FROM file_param_main where use_flag = 1 ORDER BY id";
            //达梦替换掉pgsql的NULL值更改为空字符串的函数
            if ("DmConnection".Equals(dbConnection.GetType().Name))
            {
                dbCommand.CommandText = dbCommand.CommandText.Replace("COALESCE", "ISNULL").Replace("coalesce", "ISNULL").Replace("true", "1").Replace("TRUE", "1").Replace("True", "1").Replace("false", "0").Replace("FALSE", "0").Replace("False", "0");
            }
            DbDataReader dataReader = dbCommand.ExecuteReader();
            while (dataReader.Read())
            {
                SchemaDocument schDoc = new SchemaDocument
                {
                    name = dataReader.GetString(2),
                    file_name = dataReader.GetString(1),
                    msgType = dataReader.GetString(3),
                    xmlType = dataReader.GetString(4),
                    id = dataReader.GetValue(0).ToString(),
                    prefixCols = dataReader.GetString(5),
                };

                if (!tmpDict.ContainsKey(schDoc.file_name))
                {
                    tmpDict.Add(schDoc.file_name, schDoc);
                }
            }

            string tableName = "file_param_detail";
            //根据层级初始化数据 
            int layerNum = 4;
            dataReader.Close();
            dbCommand.CommandText = "SELECT MAX(layer) layer FROM " + tableName;
            dataReader = dbCommand.ExecuteReader();
            if (dataReader.Read())
            {
                layerNum = int.Parse(dataReader.GetValue(0).ToString());
            }

            //循环获取配置元素数据
            foreach (string key in tmpDict.Keys)
            {
                SchemaDocument schDoc = tmpDict[key];
                Dictionary<int, SchemaDictionary> layerPre = new();
                for (int i = 0; i <= layerNum; i++)
                {
                    layerPre.Add(i, new SchemaDictionary());
                }

                /*****************从明细表获取************************/
                dataReader.Close();
                dbCommand.CommandText = "SELECT id,main_id,'' file_name,parent_id,child_num,idx,parent_idx,name,type,size, COALESCE(device_type, '') device_type, COALESCE(loop_val, '') loop_val,COALESCE(code, '') code,'' isalarm,'' alarmvalue, '' alarmname,issave,get_time, '' memo,layer" +
                    " FROM " + tableName + " a WHERE a.main_id = " + schDoc.id + " ORDER BY main_id, sort";
                dataReader = dbCommand.ExecuteReader();

                //动态字段
                Dictionary<string, string> dynamic = new Dictionary<string, string>();
                Dictionary<int, SchemaDictionary> schema = new();
                while (dataReader.Read())
                {
                    //层级
                    int layer = int.Parse(dataReader.GetValue(19).ToString());
                    int childNum = int.Parse(dataReader.GetValue(4).ToString());
                    if (!"".Equals(dataReader.GetString(11)) && !TransForm.IsInt(dataReader.GetString(11)) && !dynamic.ContainsKey(dataReader.GetString(11)))
                    {
                        dynamic.Add(dataReader.GetString(11), dataReader.GetString(11));
                    }

                    if (layer == 0)
                    {
                        GetElement(dataReader, schema, new SchemaDictionary() { isNode = childNum > 0 });
                        layerPre[layer] = schema[schema.Count - 1];
                    }
                    else
                    {
                        if (layerPre[layer - 1].fieldDictionary == null)
                        {
                            ((SchemaDictionary)layerPre[layer - 1]).fieldDictionary = new Dictionary<int, SchemaDictionary>();
                        }
                        GetElement(dataReader, (((SchemaDictionary)layerPre[layer - 1])).fieldDictionary, new SchemaDictionary() { isNode = childNum > 0 });
                        layerPre[layer] = (((SchemaDictionary)layerPre[layer - 1])).fieldDictionary[(((SchemaDictionary)layerPre[layer - 1])).fieldDictionary.Count - 1];
                    }
                }
                dataReader.Close();
                schDoc.dynamicParaDictionary = dynamic;
                schDoc.fieldDictionary = schema;//将已读取XML文件后的XML字段规则放进schemaDocument
                /*****************从明细表获取************************/

                string schemaxmlType = schDoc.xmlType;
                if (schemaxmlType != null && schemaxmlType != "")
                {
                    string[] xmlTypeArray = schemaxmlType.Split(",");
                    for (int i = 0; i < xmlTypeArray.Length; i++)
                    {
                        schemaDict.Add(xmlTypeArray[i].Trim(), new SchemaDocument() { rname = schDoc.name });
                    }
                }
                if (!schemaDict.ContainsKey(schDoc.name))
                {
                    schemaDict.Add(schDoc.name, schDoc);
                }
                else
                {
                    schemaDict[schDoc.name] = schDoc;
                }
            }
            try
            {
                dbCommand.Dispose();
                dataReader.DisposeAsync();
            }
            catch { }

            return schemaDict;
        }

        /// <summary>
        /// 子元素获取
        /// </summary>
        /// <param name="dataReader"></param>
        /// <param name="schema"></param>
        /// <param name="field"></param>
        private static void GetElement(DbDataReader dataReader, Dictionary<int, SchemaDictionary> schema, SchemaDictionary field)
        {
            field.id = int.Parse(dataReader.GetValue(0).ToString());
            field.name = dataReader.GetString(7);
            field.index = int.Parse(dataReader.GetValue(5).ToString());
            field.type = DataTypeUtils.getType(dataReader.GetString(8));
            //field.memo = dataReader.GetString(18);
            field.size = int.Parse(dataReader.GetValue(9).ToString());
            field.deviceType = dataReader.GetString(10);
            //field.isAlarm = "1".Equals(dataReader.GetValue(13).ToString());
            //field.alarmName = dataReader.GetString(14);
            //field.alarmValue = dataReader.GetString(15);
            field.loop = dataReader.GetString(11);
            field.code = dataReader.GetString(12);
            //如果是SchemaDictionary，即使数据库没有勾选保存，也默认保存，否则后面的取字段的逻辑可能会取不到数据
            field.isSave = field.isNode ? "1" : dataReader.GetValue(16).ToString();
            field.layer = int.Parse(dataReader.GetValue(19).ToString());
            schema.Add(schema.Count, field);
        }
    }
}
